Exploration implicite et explicite de l'espace d''etats atteignables de circuits logiques Esterel
نویسنده
چکیده
ion basée sur la profondeur des variables d’états Une première idée pour automatiser la sélection des variables à abstraire est d’utiliser la profondeur des variables d’états. Cette profondeur correspond au nombre de variables d’état sur le plus court chemin entre la variable d’état candidate à l’abstraction et les sorties des propriétés à vérifier. Cette profondeur se calcule pour l’ensemble des variables d’états du circuit par un simple parcours du graphe formant le circuit, soit avec un coût linéaire en fonction du nombre de portes. La profondeur d’une variable d’état correspond donc au “délai” par rapport à l’instant initial avec lequel la variable d’état peut influencer les propriétés à vérifier. L’idée est alors de tenter de vérifier les propriétés en abstrayant toutes les variables d’état puis, tant que les propriétés n’ont pas été validées (ou correctement invalidées avec génération de contre-exemples corrects), de réintégrer progressivement dans les calculs les variables d’état abstraites, en fonction de leur profondeur. Malheureusement, nous avons constaté que sur la plupart des circuits générés par le compilateur Esterel v5, la majorité des variables d’état sont à très faible profondeur. Cela provient essentiellement de la façon dont les continuations des parallélisations de blocs sont 3.3. RÉDUCTION DU NOMBRE DE VARIABLES POUR LE CALCUL DU RSS 59 calculées. La Figure 3.6 présente le sous-circuit généré par la mise en parallèle de trois modules. La porte sel [Ber99] indique qu’au moins une des branches du parallèle était sélectionnée. Les portes dead indiquent que la branche correspondante avait déjà terminé, c’est-à-dire qu’elle n’était plus sélectionnée alors qu’au moins une autre branche du parallèle l’était. Les portes min k0 indiquent que la branche correspondante avait déjà terminée ou vient de terminer. Les portes min k1 indiquent que la branche correspondante avait déjà terminé, vient de terminer ou est en pause. Les portes ∪ k0 indiquent qu’au moins une des branche vient de terminer. Les portes ∪ k1 indiquent qu’au moins une des branches est en pause. Un parallèle termine donc (porte k0) lorsqu’au moins une des branches vient de terminer et que toutes les autres avaient déjà terminé ou terminent également. Figure 3.6: Circuit généré pour les constructions parallèles (3 composants) Le calcul de la porte k0 référence donc tout l’arbre de sélection des branches du parallèle, donc tous les registres de pause qu’il contient. Notre analyse de profondeur ne permet donc guère de distinguer les variables d’états entre elles, a fortiori lorsque le modèle est une mise en parallèle de modules au plus haut niveau, ce qui est assez fréquent. Pour Esterel v5 9x, un simplifieur de l’arbre de sélection, scsimplify (cf. 2.5, p. 32), a été développé par Dumitru Potop-Butucaru [PB01]. Cet outil s’efforce de simplifier l’arbre lorsque certaines branches ne terminent jamais (hors préemption) ou lorsque des branches de l’arbre sont en exclusion mutuelle (séquencement). Ce simplifieur a surtout pour effet de réduire le nombre de registres du circuit –ce qui présente un intérêt non négligeable– 60 CHAPITRE 3. APPROCHE IMPLICITE mais il n’augmente guère la profondeur du circuit. Les simplifications apportées par scsimplify sont ou seront intégrées au compilateur v7. L’automatisation de l’abstraction à partir des niveaux de profondeur des registres sera donc à reconsidérer lorsque le compilateur v7 aura atteint sa maturité... Analyse des réfutations erronées Les techniques de remplacement de variables d’états par des entrées libres ou d’abstraction de variables à l’aide d’une logique trivaluée calculent des sur-approximations de l’espace d’états car elles opèrent sur un modèle simplifié. La confrontation des propriétés énoncées par l’utilisateur avec des espaces d’états sur-approchés peut conduire à réfuter ces propriétés sur le modèle abstrait à une certaine profondeur alors qu’elles sont tout à fait valides sur le modèle concret à cette profondeur. Les réfutations erronées (false negatives) se détectent très simplement lors de la génération de contre-exemples menant à la violation des propriétés. Ces contre-exemples sont générés sur le modèle concret par calculs d’images inverses des fonctions de transitions. Il s’agit alors de trouver des séquences d’entrées qui, à partir de l’ensemble d’états atteignables découverts à la profondeur précédente, mènent à des états violant les propriétés. Si de telles séquences, envisageables sur le modèle abstrait, ne peuvent être trouvées sur le modèle concret, alors les calculs d’images inversent échoueront à un moment ou à un autre. A partir de là, plusieurs attitudes sont envisageables. L’attitude minimale consiste à poursuivre l’exploration des espaces d’états atteignables dans le but de déterminer si les propriétés peuvent réellement être violées à une profondeur plus importante. Il est également envisageable de mettre à jour les espaces d’états atteignables en supprimant les états qui n’ont pas été confirmés comme réellement accessibles sur le modèle concret lors des calculs d’images inverses. Cette option vise à limiter l’effet “boule de neige” en supprimant des sur-approximations construites les états qui ne sont pas réellement accessibles. Cette option peut néanmoins impliquer un coût prohibitif de mise à jour en cascade des ensembles d’états atteignables. Nous n’avons pas évalué cette option. Dans le cadre d’une abstraction automatisée du modèle, la détection de réfutations erronées dues à une abstraction excessive peut conduire à un raffinement de l’abstraction visant à éliminer les réfutations erronées. Il existe dans la littérature de nombreux travaux proposant diverses stratégies de raffinement des abstractions par analyse des contreexemples erronés [CGJ00, GD00, WHL01]. Ces différentes méthodes de raffinement de l’abstraction nécessitant au préalable d’automatiser celle-ci, nous ne les avons pas étudiées plus profondément. 3.3.5 Travaux connexes Dans le cadre des calculs d’approximations par excès de l’espace d’états atteignables d’un modèle, une des approches connexes à la nôtre est basée sur la décomposition du modèle. Dans [CHM93], Cho et al. proposent un algorithme qui décompose l’ensemble des 3.4. UTILISATION DES INFORMATIONS STRUCTURELLES SUR LES MODÈLES61 variables d’états en sous-ensembles disjoints. Chaque sous-ensemble est utilisé pour calculer une partie de l’espace d’états atteignables, le résultat final étant le produit cartésien de ces parties d’espaces d’états atteignables. Ces travaux ont été étendus aux sous-ensembles de variables d’états non disjoints par Govindaraju et al. dans [GDHH98], puis raffiné dans [GDB00] par l’ajout de variables d’état auxiliaires permettant d’accrôıtre la corrélation entre les sous-ensembles de variables d’états. L’extensions aux calculs d’image inverses est proposé dans [GD98]. Le raffinement des choix de partitionnement basé sur l’analyse des contre-exemples erronés est proposée dans [GD00]. Ces travaux remplacent par des entrées libres les variables d’états ne faisant pas partie des sous-ensembles de variables d’états considérés : il serait possible d’appliquer à ces travaux notre technique à base de logique trivaluée. 3.4 Utilisation des informations structurelles sur les modèles La plupart des langages de haut-niveau offrent la possibilité de décomposer les programmes en modules, alors utilisés de manière hiérarchique. Avec le langage Esterel, la hiérarchisation apportée par les modules est encore renforcée par la hiérarchisation des constructions du langage, comme le montre par exemple le Programme 2.2 (p. 22). La structure hiérarchique des modules et des constructions du langages se retrouve dans l’arbre de sélection (cf. 2.3.5, p. 28), qui indique la hiérarchie des registres de pause, ou variables d’états. Ces registres de pause sont générés explicitement par l’instruction pause et implicitement par les instructions dérivées l’utilisant (halt, await, etc.). L’arbre de sélection indique des compatibilités (exécution en parallèle) ou des exclusions (exécution en séquence) entre registres de pause ou grappes de registres de pause. Nous proposons ici quelques méthodes tirant partie de ces informations structurelles de haut-niveau, avec toujours comme objectif la réduction des coûts de calculs d’espace d’états atteignables. 3.4.1 Approximation syntaxique de l’espace d’états accessibles A partir de l’arbre de sélection du programme, nous pouvons construire un BDD qui exprime une approximation par excès de l’espace d’états atteignables du circuit. Les états déclarés non atteignables par ce BDD le sont effectivement par construction. La Figure 3.7 présente un tel BDD, correspondant au Programme 2.6. La construction d’un tel BDD se fait en remontée d’un simple parcours en profondeur de l’arbre de sélection. En utilisant un ordre de variable cohérent avec la structure des registres dans le programme initial, le temps de construction du BDD et sa taille finale sont négligeables. Les propriétés ne dépendant que du fait que certaines parties de programmes ne puissent être actives en même temps par construction pourraient ainsi être vérifiée à moindre frais, en évitant un calcul d’espace d’états coûteux. Notre outil de vérification formelle propose 62 CHAPITRE 3. APPROCHE IMPLICITE Figure 3.7: BDD de l’arbre de sélection du Programme 2.6 une telle fonctionnalité. Néanmoins, nous devons reconnâıtre n’avoir jamais rencontré de telles propriétés sur les modèles que nous avons analysés. 3.4.2 Renforcement des relations entre variables remplacées par des entrées libres Les relations exprimées par l’arbre de sélection peuvent être utilisées pour renforcer les contraintes entre les variables d’état qui ont été remplacées par des entrées libres. Ces relations enrichissent alors l’input care set (J ) spécifié par le développeur, qui décrit des contraintes entre les entrées du modèle (cf. 2.7, p. 35). Cette technique vise deux objectifs : 1. limiter la sur-approximation due au relâchement des contraintes entre les variables d’états remplacées par des entrées libres en réintégrant les contraintes les plus simples (les exclusions provenant des séquencements) ; limiter la sur-approximation revient à réduire le cardinal de l’espace d’états atteignables et peut rendre vérifiable une propriété qui ne l’était sur un espace d’états excessivement sur-approché ; 2. réduire le nombre de nœuds des BDDs en restreignant ceux-ci à un domaine plus strict (via l’opérateur Restrict [CM90]). L’input care set pouvant référencer à la fois des variables d’états et des entrées, nous pouvons donc y intégrer toutes les relations spécifiées par l’arbre de sélection qui référencent au moins une variable d’état remplacée par une entrée libre. En pratique, les bénéfices apportés par cette technique ne sont pas généralisables. La réduction de la sur-approximation est notable dans de nombreux cas, mais elle s’effectue souvent au prix d’un ralentissement des calculs et d’une augmentation de la consommation mémoire (cf. Expériences 6.4, p. 118 et 6.5, p. 125). 3.4. UTILISATION DES INFORMATIONS STRUCTURELLES SUR LES MODÈLES63 3.4.3 Borne supérieure d’approximation Les relations exprimées par l’arbre de sélection peuvent aussi être utilisées comme borne supérieure de l’espace d’états atteignables. A la fin de chaque étape du calcul d’espace d’états atteignables, nous ne conservons alors que l’intersection entre les nouveaux états découverts et le BDD d’approximation dérivé de l’arbre de sélection. Une partie des états découverts atteignables à tort sont donc automatiquement supprimés, ce qui réduit l’effet “boule de neige”, donc la sur-approximation. Les variables abstraites à l’aide d’une logique trivaluée disparaissent complètement en tant que variables. Elles ne peuvent donc pas apparâıtre dans un BDD quel qu’il soit. De même, les variables d’états remplacées par des entrées libres ne peuvent apparâıtre dans le BDD bornant l’espaces d’états atteignables, qui ne peut référencer que des variables d’états. Nous ne construisons donc le BDD de borne supérieure de l’espace d’états atteignables qu’à partir des relations de l’arbre de sélection restreintes aux variables d’états conservées en tant que telles. En pratique, les bénéfices apportés par cette technique sont déjà plus notables. La réduction des temps de calculs et de consommation mémoire sont souvent significatifs. Le cardinal des espaces d’états atteignables est souvent réduit d’un ou plusieurs ordres de grandeur, ce qui permet parfois de rendre certaines propriétés vérifiables (cf. Expériences 6.4, p. 118 et 6.5, p. 125). 3.4.4 Stratégies d’ordonnancement des variables Construire des BDDs dérivés de l’arbre de sélection pose le problème du choix d’un ordonnancement de variables. Plusieurs approches sont possibles : 1. utiliser le même ordonnancement de variables —calculé à partir d’heuristiques basées sur la topologie du circuit— à la fois pour la construction des BDDs dérivés de l’arbre de sélection et pour le calcul d’espace d’états atteignables ; cette stratégie semble être pénalisante pour la construction des BDDs dérivés de l’arbre de sélection : les temps de construction ainsi que le nombre de nœuds de BDDs construits semblent souvent ne pas être optimaux ; 2. appliquer un ordonnancement des variables cohérent avec la structure des registres dans le programme initial puis utiliser ce même ordonnancement pour le calcul d’espace d’états atteignables ; cette stratégie permet de construire des BDDs dérivés de l’arbre de sélection de taille très compacte et en temps négligeable, mais cet ordonnancement ne semble pas favoriser l’efficacité des calculs d’espaces d’états ; 3. utiliser un premier ordonnancement de variables cohérent avec la structure des registres, le temps de construire les BDDs dérivés de l’arbre de sélection, puis mettre à jour ces BDDs afin qu’ils respectent l’ordonnancement des variables calculé à partir d’heuristiques basées sur la topologie du circuit ; cette stratégie présente un risque d’explosion en temps et/ou en mémoire précisemment lors du réordonnancement des BDDs dérivés de l’arbre de sélection. 64 CHAPITRE 3. APPROCHE IMPLICITE Après diverses expériences, l’approche que nous avons retenue est cette dernière qui, en pratique, semble offrir le meilleur compromis quant aux temps de calculs et à la consommation mémoire. Les cas d’explosion en temps et/ou en mémoire lors du réordonnancement des BDDs semblent rares en pratique. Dans tous les cas, un comportement suspect lors de cette phase, qui pourrait empêcher l’obtention de résultats, est aisément détectable par l’utilisateur. 3.5 Représentation interne des circuits Le package de BDDs que nous utilisons, TiGeR [CMT93], calcule l’espace d’états accessibles de circuits logiques représentés par des structures C qui lui sont propres et forment un Tgr Network. Selon le type de circuit donné en entrée, notre outil propose trois différents flots de construction de Tgr Networks (Figure 3.8). Figure 3.8: Flots de création de Tgr Networks 3.5. REPRÉSENTATION INTERNE DES CIRCUITS 65 3.5.1 Construction directe de Tgr Networks à partir de circuits au format BLIF La première méthode, utilisée par Xeve, consiste à se reposer sur une fonction fournie par le package TiGeR et permettant le chargement direct d’un circuit au format BLIF ainsi que sa conversion en Tgr Network. Les circuits au format BLIF sont dérivés des circuits Esterel (cf. Figure 2.5, p. 30), mais ils n’en conservent que la logique et perdent toute information structurelle sur les modèles. 3.5.2 Construction de Tgr Networks à partir de circuits au format interne sc La deuxième méthode consiste à travailler directement sur les circuits Esterel, afin justement de permettre l’utilisation de ces informations structurelles (cf. 3.4, p. 61). Les circuits Esterel, au format interne sc, sont d’abord chargés par la librairie common, librairie commune à différents processeurs et dédiée au chargement des fichiers intermédiaires du compilateur. Ces circuits sont alors convertis en Tgr Network par notre librairie TiGeREnh. Les Tgr Networks sont des graphes acycliques dont les nœuds sont des PLAs (Programmable Logic Array), plus précisément des fonctions combinatoires en forme normale (somme de produits). A chaque nœud d’un Tgr Network sont associés plusieurs variables. Le nombre de variables disponibles est limité : sur des architectures 32 bits, les variables de BDDs sont stockées dans les 16 premiers bits du premier mot de la structure correspondant à un nœud de BDD (Figure 3.9). Cela limite donc le nombre de variables disponibles à 65 536 et à encore moins le nombre maximal de nœuds dans un Tgr Network. Figure 3.9: Têtes de nœuds de BDDs Les autres bits sont utilisés pour stocker le nombre de références faites à ce nœud (pour le Garbage Collector) et par des drapeaux indiquant si le nœud est terminal ou s’il est inversé. Pour augmenter le nombre de variables disponibles, il est donc possible de réduire l’espace utilisé pour stocker les compteurs de références, ce qui en limite alors la valeur maximale. Lorsqu’un compteur de références atteint la valeur maximale, le nœud correspondant devient immortel : la mémoire qu’il occupe et, par transitivité, tous les nœuds de BDDs référencés à partir de celui-ci ne peuvent alors plus être récupérés par le Garbage Collector. Enfin, la taille d’un grand nombre de structures (essentiellement des tables de correspondances) dépend du nombre maximal de variables. Augmenter le nombre de variables disponibles se fait donc au prix d’un risque notable d’augmentation de la consommation mémoire. 66 CHAPITRE 3. APPROCHE IMPLICITE L’approche de Xeve, qui consiste à construire directement le Tgr Network à partir du circuit BLIF puis à effectuer le sweeping (à partir de la version v5 94), consomme donc inutilement des variables : les variables des nœuds supprimés ne sont pas récupérées. La construction de Tgr Network à partir de circuit sc nous permet de réduire la consommation de variables car nous effectuons le sweeping à la volée, en construisant le Tgr Network à partir des sorties des propriétés à vérifier. Sur certains gros modèles, il était nécessaire d’utiliser une version spéciale de Xeve, compilée pour permettre plus de variables au détriment donc du seuil d’immortalité des nœuds de BDDs, alors que notre outil traitait le circuit en version standard. 3.5.3 Représentation intermédiaire du circuit par un AIGraph Les diverses analyses de circuits que nous avons mises en œuvre nécessitent d’associer, parfois temporairement, des structures de données spécifiques aux différents nœuds du circuit analysé. L’implémentation de ces analyses par extension des structures formant un Tgr Network n’était guère pratique : – Dans TiGeR, l’association de données temporaires à des nœuds de Tgr Networks se fait via des tables d’adressages dispersées qui maintiennent les associations. Cette approche, si elle résout de manière assez correcte le besoin d’associer temporairement des données aux nœuds du graphe est intrinsèquement lourde. – TiGeR est écrit en C. Même si cela a été fait avec une approche objet très forte et que le résultat est d’une rare qualité, les contortions nécessaires pour parvenir à encapsuler les données, la perte de typage statique fort (auquel nous tenons dans nos développements) et les transtypages (casts) incessants que cela requiert sont lourds lorsqu’on a la possibilité de faire mieux, en l’occurrence en C++. – Enfin, si les PLAs des nœuds de Tgr Networks sont très versatiles, puisqu’il permettent d’exprimer toutes sortes de fonctions combinatoires, leur manipulation n’en est pas moins complexe. De manière similaire, il n’était pas envisageable de développer nos analyses en utilisant directement les structures de données que la librairie common instancie à partir des circuits au format sc. En effet, cette librairie ne facilite pas plus, voire rend difficile, l’association de données aux nœuds du graphe représentant le circuit. Nous avons donc choisi de développer nos analyses de circuits sur une nouvelle structure de graphe. Bien qu’un quelconque graphe de portes logiques soit satisfaisant, dès lors que l’on en a la mâıtrise de l’implémentation, nous nous sommes orientés vers l’utilisation d’un And/Inverter Graph, ou AIGraph, proposé par Andreas Kuehlmann et al. [KK97, GK00, PK00, KGP01]. Cette structure de données est très simple à manipuler, permet aisément d’implémenter des analyses de graphes et peut permettre une compression de circuits à la volée. La librairie common a depuis été réécrite en v7, avec notamment la volonté de permettre l’extension des classes instanciées à partir des fichiers intermédiaires du compilateur. 3.5. REPRÉSENTATION INTERNE DES CIRCUITS 67 Les nœuds d’un AIGraph sont restreints à des portes et binaires. Les références à ces nœuds peuvent être inversées par marquage du bit de poids faible du pointeur, à l’instar de ce qui est fait dans la plupart des librairies de BDDs. La conversion de nœuds arbitraires de circuits logiques en de telles portes et binaires se fait trivialement, à la volée lors de la construction du circuit, par application des lois de De Morgan. Cette conversion de portes n-aires en portes binaires n’est certes pas linéaire (elle est d’ordre n · log (n)), mais la majeure partie des portes générées par le compilateur Esterel sont binaires. Nous n’attendons donc pas d’augmentation notable du nombre de portes suite à la mise en œuvre de cette technique. Similairement à ce qui est fait dans les librairies de BDDs, les nœuds sont stockés dans une table d’adressage dispersé. Le code de hachage est calculé à partir des identificateurs des nœuds fils et de leur attribut de négation. La table d’adressage dispersé est utilisée pour détecter —à coût pratiquement nul— les nœuds identiques, donc les souscircuits isomorphes. Ces sous-circuits isomorphes étant fonctionnellement équivalents, ils sont immédiatement fusionnés. La canonicité structurelle des sous-circuits est renforcée par leur restructuration jusqu’au second niveau (nœuds petit-fils), ce qui augmente encore la détection de sous-circuits isomorphes [GK00] sans surcoût notable. Cette structure de données avait initialement été utilisée par Andreas Kuehlmann et al. pour la vérification formelle d’équivalence de machines (equivalence checking). Dans ce contexte, on vise justement à détecter des sous-circuits fonctionnellement équivalents, ce qui simplifie le miter analysé (cf. 2.10.3, p. 45). Par exemple, dans [PK00, KGP01], l’apport de l’AIGraph comme structure de base est renforcé par l’alternance de passes de BDD sweeping —dans lesquelles on se sert de la représentation canonique des fonctions qu’offrent les BDDs pour identifier des sous-circuits fonctionnellement équivalents— et de passes de SAT solver —pour vérifier l’équivalence de certaines portes. En ce qui nous concerne, la vérification formelle d’équivalence de machines ne représente par un domaine significatif d’application de nos outils. Nous ne nous attendons donc pas à travailler sur des circuits redondants par construction. Néanmoins, les circuits générés de manière automatique ont souvent une certaine quantité de nœuds redondants [GK00]. Les circuits générés par le compilateur Esterel, a fortiori s’ils proviennent de programmes SyncCharts ou autres, n’échappent probablement pas à la règle. De plus, la section suivante présente une fonctionnalité qui peut conduire à des registres redondants. Ces registres redondants seront automatiquement fusionnés —à coût pratiquement nul— par l’AIGraph. La compression à la volée des circuits analysés n’était donc pas l’objectif recherché, d’autant plus que l’AIGraph, dans les travaux d’Andreas Kuehlmann et al., est censé être utilisé en conjonction avec d’autres techniques permettant de compresser les circuits. Nos expériences semblent cependant indiquer une légère simplification du circuit, ce qui a un impact sur la consommation de variables de BDDs. Nous avions donc choisi l’AIGraph essentiellement pour sa simplicité : c’est une structure de données très versatile qui facilite l’implémentation de la plupart des analyses de circuits. Nous envisageons de généraliser son utilisation à nos outils d’analyse explicite ou hybride implicite/explicite de circuits (Chapitres 4 et 5), ce qui permettrait de simplifier 68 CHAPITRE 3. APPROCHE IMPLICITE les algorithmes de stabilisation des circuits qui y sont mis en œuvre. 3.6 Vérification formelle en bôıte blanche ou noire La vérification formelle par observateurs [HLR93] (cf. 2.10, p. 44) consiste à exécuter, en parallèle du modèle à vérifier, un ou des modules dont les entrées sont celles du modèle observé ainsi que ses sorties, dont la correction est contrôlée. Initialement, l’instanciation des observateurs était à la charge de l’utilisateur. Les observateurs pouvaient tout autant être exécutés en parallèle au plus haut niveau du modèle observé ou plus profondément dans l’arbre d’instanciation des modules. Les signaux émis par l’observateur devaient toutefois faire partie de l’interface du modèle, de façon à être visibles par le vérifieur. Cette méthodologie de vérification est dite en bôıte blanche : l’observateur peut avoir accès aux entrées et aux sorties primaires du modèle observé, mais aussi à toute donnée (signaux locaux, variables, etc.) visibles dans sa portée d’instanciation. L’approche en bôıte blanche amène par contre l’inconvénient que le modèle doit être compilé différemment selon qu’il est destiné à la production ou à la vérification formelle, autrement dit s’il doit intégrer ou non les observateurs. Comme nous l’avons vu en 3.3.4 (p. 58), le câblage des modules exécutés en parallèle a tendance à lier les supports des modules parallélisés. Or, la vérification formelle par observateur revient généralement à des parallélisations au plus haut niveau. Dans le cas où l’observateur ne vérifie en fait qu’une petite partie du circuit, il se peut que le sweeping soit sans effet et que l’on doive calculer l’espace d’états atteignables du circuit avec tous ses registres. Pour s’affranchir de ce problème, nous proposons de compiler les observateurs séparément, l’édition de liens étant alors effectuée par le vérifieur formel et non plus par le compilateur Esterel. Cette approche est dite en bôıte noire parce que l’observateur n’a accès qu’aux entrées et aux sorties primaires du modèle observé. Elle permet d’accrôıtre le champs d’action du sweeping et de ne pas nécessiter différentes compilations selon que le modèle doit être vérifié ou produit. Enfin, si les observateurs ont des structures d’implémentation similaires (des boucles d’attentes de signaux par exemple), ils auront probablement des registres de pauses équivalents entre eux, mais aussi équivalents à certains registres de pause du modèle observé. La structure d’AIGraph vue à la section précédente permet de fusionner ces registres redondants à coût pratiquement nul. 3.7 Bounded Model Checking Le Bounded Model Checking consiste à ne calculer l’espace d’états atteignables du modèle que jusqu’à une certaine profondeur et, en conséquence, à ne vérifier le modèle que jusqu’à cette profondeur. Cette technique est utile pour permettre, notamment au début des développements, de limiter la profondeur d’analyse pour en diminuer le coût : on ne 3.8. INGÉNIERIE D’EVCL ET DE LA LIBRARIE TIGERENH 69 cherche alors qu’à vérifier la surface du modèle, ce qui permet de détecter les erreurs les plus facilement atteignables. Cette technique peut être obligatoire pour les SAT solvers qui ne savent pas découvrir par eux-même le diamètre du modèle, ou qui ne savent le faire qu’avec un surcoût encore inadmissible. Notre outil propose une telle fonctionnalité. Dès lors, il semblerait intéressant d’essayer de tirer partie de la limitation de profondeur d’analyse pour réduire le coût de celle-ci. A la manière du sweeping (cf. 3.1.1, p. 49), qui spécialise le circuit analysé en fonction des propriétés à vérifier, nous aimerions spécialiser le circuit en fonction de la profondeur considérée. Cela revient à faire disparâıtre les registres qui n’interviennent pas dans les niveaux de profondeur considérés et ne deviennent actifs que dans les instants ultérieurs, et à les remplacer par une constante. Malheureusement, comme nous l’avons vu en 3.3.4 (p. 58), la majorité des registres sont à très faible profondeur dans les circuits générés par le compilateur Esterel v5. Cette optimisation sera donc à reconsidérer en fonction des améliorations apportées au câblage des circuits par la version v7 du compilateur Esterel... 3.8 Ingénierie d’evcl et de la librarie TiGeREnh 3.8.1 Fournitures d’information supplémentaires à des écouteurs Le pilotage de la librairie TiGeREnh se fait de manière standard par appels de méthodes, les résultats des calculs étant retournés par ces méthodes. Toutes les informations supplémentaires que la librairie est susceptible de fournir, comme par exemple des détails concernant la progression des calculs, se font selon le principe des écouteurs (listeners) : tout module intéressé par de telles informations s’enregistre comme écouteur auprès de la librairie en fournissant une instance de la classe d’écouteur adéquate. Les différentes méthodes de cette classe seront invoquées au moment opportun, avec les informations disponibles. Cette technique permet d’accrôıtre de manière notable la versatilité de la librairie, puisqu’elle détache celle-ci de toute nécessité de connâıtre les modules auquels elle doit communiquer des informations. Par exemple, evcl pilote la librarie par appels de méthodes et transmet à l’utilisateur les résultats demandés par affichage sur la sortie standard ou dans des fichiers (comme pour les contre-exemples). Si l’utilisateur a activé le mode verbeux, différents écouteurs dont la seule tâche consiste à afficher sur la sortie d’erreur standard les informations qui leurs sont fournies sont enregistrés auprès de la librairie. De manière similaire, il est possible d’activer la production de fichiers XML permettant de conserver ces mêmes informations. Un script PHP trivial permet alors l’extraction de ces données et leur conversion en tableaux au format standard CSV (comma separated values), directement utilisables par Excel r © c ©A ou tout autre tableur/grapheur. Ce choix d’architecture avait aussi été fait dans le but de permettre le développement rapide d’une interface graphique facilitant l’utilisation de l’outil... 70 CHAPITRE 3. APPROCHE IMPLICITE 3.8.2 Vérification (informelle) du vérifieur Les outils de vérification formelle ayant pour objectif de valider ou d’invalider de façon définitive les modèles qui leur sont soumis, il importe de mettre en œuvre tous les moyens raisonnables pour garantir leur correction : il n’est guère concevable qu’il subsiste la moindre part de doute dans les algorithmes utilisés ou leur implémentation. Notre outil evcl et la librairie qu’il pilote, TiGeREnh, sont écrit en C++. La librairie de BDDs embarquée, TiGeR, est écrite en C. La vérification formelle de programmes de telle taille, a fortiori écrits dans de tels langages génériques, n’est toujours pas envisageable dans un avenir proche. De plus, les outils à base de BDDs, friands d’arithmétique de pointeurs et de manipulations de données au niveau des bits, ne peuvent se contenter d’un sous-ensemble vérifiable du langage. Il existe certes différentes tentatives d’utilisation de prouveurs de théorèmes comme Coq [Tea02] pour la vérification d’algorithmes mis en œuvre par exemple dans les outils de vérification formelle [AM00]. Néanmoins, le manque actuel d’automatisation des prouveurs de théorèmes et l’importance de l’investissement requis pour permettre aux prouveurs de théorèmes d’interpréter correctement des structures de données souvent complexes [BMZ02] impliquent que de telles tâches doivent être effectuées dans une thèse séparée... De ce fait, notre outil de vérification formelle n’est actuellement validé que de manière informelle, selon deux approches complémentaires : par auto-contrôle de l’outil et des librairies et par contrôle externe des résultats produits. L’auto-contrôle du programme est réalisé selon des paradigmes de programmation défensive usuels, plus précisemment ceux de la programmation par contrat (Design by Contract) [Mey88, Mey91], bien que le langage C++ ne facilite guère la mise en œuvre de tels mécanismes. Nous nous attachons donc, au sein même des implémentations, à vérifier en permanence la validité des données manipulées. En sortie des fonctions, nous nous efforçons autant que faire se peut de contrôler la validité des résultats retournés en vérifiant les propriétés notables que ces données sont censées avoir. Il est alors commun de constater des différences de performances de plusieurs ordres de grandeur entre les versions de nos outils avec ou sans contrôles internes. Ainsi, une exécution de nos outils qui ne lève pas d’assertion est déjà un bon gage de crédibilité des résultats produits. Cette confiance est renforcée par un banc de test que nous avons réalisé en PHP. Ce banc de test se charge d’initier la vérification formelle de différents programmes et de contrôler la validité des résultats produits, dont notamment : – la terminaison correcte de l’outil ; – la validité des analyses des propriétés (réfutables ou non) ; – le réalisme des éventuels contre-exemples ; – la cohérence des représentations internes des circuits, quelle qu’ait été la méthode de construction (cf. 3.5, p. 64) ; – la correction du cardinal de l’espace d’états atteignables ; – la correction du cardinal des ensembles d’états atteignables aux différents niveaux de profondeurs. Ce banc de test pourrait encore être amélioré en vérifiant les BDDs des espaces d’états 3.9. GÉNÉRATION DE SÉQUENCES DE TESTS EXHAUSTIVES 71 atteignables totaux ou à chaque niveau de profondeur. De même, il serait possible de contrôler que les espaces d’états atteignables générés en remplaçant certaines variables d’états par des entrées libres ou en abstrayant certaines variables à l’aide d’une logique trivaluée soient bien des sur-ensembles de l’espace d’états atteignables du modèle original. 3.9 Génération de séquences de tests exhaustives La génération de séquences de tests exhaustives permet de contrôler la conformité de deux implémentations à différents niveaux d’abstraction. Par exemple, il est possible de modéliser une application en langage de haut-niveau (comme les SyncCharts), pour la vitesse de développement et la lisibilité du résultat, puis d’implémenter cette application en langage de plus bas niveau (comme VHDL, Verilog ou un langage propriétaire), pour la production. On génère alors à partir de la description de haut-niveau des séquences de tests exhaustives qui couvrent l’ensemble des comportements du modèle. La réaction des deux implémentations à ces séquences de tests doit concorder. Nous n’avons pas étudié personnellement le problème de la génération de séquences de tests par des techniques purement implicites. Cela a été fait par Amar Bouali, au sein d’Esterel Technologies, et nous présentons l’approche qu’il a choisie. Comme nous le verrons en 5.4 (p. 110), il nous semble préférable d’aborder ce problème à l’aide de techniques hybrides implicites/explicites. La solution proposée vise la couverture comportementale du modèle, selon différents objectifs : – Couverture d’états : cette couverture garantit que tous les états sont visités au moins une fois par les tests. – Couverture de transitions entre paires d’états : cette couverture garantit que, s’il existe une transition possible entre deux états, elle sera empruntée au moins une fois par les tests. S’il existe différentes transitions possibles entre deux états (cf. Figure 4.10(a), p. 95), une seule est empruntée. – Couverture d’outputs : cette couverture garantit que tous les chemins directs — autrement dit sans cycles— conduisant à l’émission d’un certain output sont générés. Afin de s’assurer que les séquences de tests générées automatiquement demeurent compréhensibles par le développeur, deux types de séquences sont proposées : – Séquences courtes : la longueur de chaque séquence ne peut être supérieure au diamètre du modèle. – Séquences longues : les séquences peuvent être plus longues que le diamètre du modèle, mais leur longueur peut être limitée à la demande. La génération de tests se fait en deux temps : 1. Dans un premier temps, l’espace d’états atteignables du modèle est calculé. Pour le cas spécifique de la couverture de transitions, il est nécessaire de construire le graphe des paires d’états entre lesquels une transition est possible. 72 CHAPITRE 3. APPROCHE IMPLICITE 2. Dans un second temps, ces graphes sont parcourus en arrière à partir des profondeurs les plus basses afin de générer les séquences d’entrées les couvrant. Les parcours en arrière sont réalisés par des calculs d’images inverses, dont les résultats sont mémorisés dans des structures de mémoire cache. Dans cette approche de la génération de séquences de tests, les techniques mises en œuvre sont purement symboliques. L’espace d’états atteignables est calculé de manière usuelle comme nous l’avons vu en 2.9 (p. 38). Les états ou les paires de transitions visitées sont stockés dans des BDDs. En pratique, les coûts en temps et en mémoire de calcul de l’espace d’états atteignables du modèle et la taille des séquences générées limitent la génération de séquences de tests exhaustives aux modèles de taille moyenne, voire à des sous-modules du modèle. Cela est d’autant plus vrai pour la couverture de transitions, qui nécessite de doubler le nombre de variables d’états impliquées dans le calcul d’espace d’états atteignables. Pour de nombreuses raisons, nous ne pensons pas qu’une approche purement implicite soit appropriée à la génération de séquences de tests exhaustives. Certes, les calculs d’espaces d’états atteignables sont généralement beaucoup moins coûteux avec les techniques implicites qu’avec les techniques explicites. Cette différence de coût n’est probablement plus la même dans le cadre de la couverture de transitions, où les techniques implicites imposent de doubler le nombre de variables de BDDs impliquées. De plus, doubler ce nombre de variables ne permet de conserver qu’une information encore grossière sur la structure des transitions entre états : cela permet d’indiquer uniquement si une transition entre deux états est possible. Connâıtre plus finement la structure des transitions entre états nécessiterait en plus de conserver dans les BDDs les variables d’entrées, ce qui ferait encore empirer les coûts de construction des graphes de transitions. Avec les techniques explicites, les différences de coût pour l’obtention d’informations de différente granularité concernant la structure des transitions entre états est beaucoup moins marquée. De plus, en terme d’implémentation, la représentation en intention de l’espace d’états atteignables ne facilite pas l’exploration de celui-ci. Il est nécessaire de stocker de nombreuses informations comme les états ou les transitions couvertes dans des BDDs séparés, sans cesse mis à jour par des opérations au coût non constant. De même, la génération de valuations d’entrées permettant la transition d’un état à un autre se fait par des calculs d’image inverses coûteux. La mémorisation dans des structures de mémoire cache des résultats de ces calculs d’images inverses évite certes de répéter sans cesse les mêmes calculs mais n’évite pas le coût des premiers calculs. Enfin et surtout, la génération de séquences de tests implique de manière intrinsèque une exploration énumérative de la structure de l’espace d’états atteignables : l’inconvénient principal des techniques explicites n’en est donc plus un dès lors que l’énumération devient incontournable. Un outil de génération de séquences de tests par une approche purement explicite a été développé par une des équipes de consultants d’Esterel Technologies (cf. 4.4, p. 101). Leur approche est basée sur l’analyse des automates explicites produits par notre générateur
منابع مشابه
The steam boiler controller problem in esterel and its
We describe the use of the veriication tools xeve and fc2symbmin on the esterel encoding of a Steam Boiler controller proposed by J.R. Abial. xeve is a veriication tool set dedicated to the analysis of synchronous reactive systems in the form of boolean equations, using the symbolic representation of BDDs for implicit state representation. fc2symbmin is a latter addition to this toolset, and al...
متن کاملTrajectory planning in a dynamic workspace: a 'state-time space' approach
This report addresses trajectory planning in dynamic workspace, i.e. motion planning for a robot subject to dynamic constraints and moving in a workspace with moving obstacles. First is introduced the novel concept of state-time space, i.e. the state space of the robot augmented of the time dimension. Like connguration space which is a tool to formulate path planning problems, state-time space ...
متن کاملA Fast Algorithm for Lacunary Wavelet Bases Related to the Solution of Pdes
{ We describe a transform for locally reened wavelet bases which employs the cardinal Lagrange function instead of the scaling function. This construction is extended to biorthogonal vaguelettes into which a diierential operator is incorporated. The approach is relevant for the solution of nonlinear parabolic PDEs by an explicit or semi{ implicit time scheme when the nonlinear term is evaluated...
متن کاملPlanning Motion Strategies in the Contact Space under Geometric Uncertainty Constraints
R esum e. Ce travail pr esente une approche de planiication de mouvements de robots contraints par l'incertitude g eom etrique. Les contacts entre le robot et les obstacles sont utilis es pour r eduire l'incertitude de position et d'orientation et guider le robot vers son but. Deux types de mouvements sont consider es par le processus de planiication : des mouvements dans l'espace libre (ou des...
متن کاملLa représentation formelle des concepts spatiaux dans la langue
Dans ce chapitre, nous faisons l'hypothèse que l'étude systématique de la sémantique des marqueurs spatiaux de la langue permet de mettre en évidence certaines propriétés et concepts fondamentaux caractérisant les représentations conceptuelles de l'espace. Nous proposons un système formel rendant compte des propriétés révélées par les analyses linguistiques, et nous utilisons ces outils pour re...
متن کامل